/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2007 INESC Porto
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
 */

#ifndef TEXCP_HEADER_H
#define TEXCP_HEADER_H

#include <stdint.h>
#include <vector>
#include "ns3/header.h"
#include "ns3/ipv4-address.h"
#include "ns3/nstime.h"
#include "ns3/tag.h"

namespace ns3 {

namespace texcp_routing{

struct IEPair
{
  /// Ingress Address
  Ipv4Address ingressAddr;
  /// Egress Address
  Ipv4Address egressAddr;
};

static inline bool
operator == (const IEPair &a, const IEPair &b)
{
 return (a.ingressAddr == b.ingressAddr
         && a.egressAddr == b.egressAddr);
}

static inline bool
operator < (const IEPair &a, const IEPair &b)
{
 return ((a.ingressAddr < b.ingressAddr) || 
         (a.ingressAddr == b.ingressAddr && a.egressAddr < b.egressAddr));
         
}
static inline std::ostream&
operator << (std::ostream &os, const IEPair &pair)
{
 os << "Ingress Address =" << pair.ingressAddr
    << ", Egress Address =" << pair.egressAddr;
 return os;
}

class TexcpHeader : public Header 
{
public:
  TexcpHeader ();
  virtual ~TexcpHeader ();

  /*void SetPacketLength (uint16_t length)
  {
    m_packetLength = length;
  }
  uint16_t GetPacketLength () const
  {
    return m_packetLength;
  }

  void SetPacketSequenceNumber (uint16_t seqnum)
  {
    m_packetSequenceNumber = seqnum;
  }
  uint16_t GetPacketSequenceNumber () const
  {
    return m_packetSequenceNumber;
  }*/
  void SetPathUtilization (double length)
  {
    memcpy(&m_path_utilization, &length,8);
  }
  double GetPathUtilization () const
  {
    double d;
    memcpy(&d, &m_path_utilization, 8);
    return d;
  }
  void SetPositiveFeedback (double length)
  {
    memcpy(&m_positive_feedback, &length, 8);
  }
  double GetPositiveFeedback () const
  {
    double d;
    memcpy(&d, &m_positive_feedback, 8);
    return d;
  }
  void SetNegativeFeedback (double length)
  {
    memcpy(&m_negative_feedback, &length,8);
  }
  double GetNegativeFeedback () const
  {
    double d;
    memcpy(&d, &m_negative_feedback, 8);
    return d;
  }
  void SetWeight (double length)
  {
    memcpy(&m_weight, &length, 8);
  }
  double GetWeight () const
  {
    double d;
    memcpy (&d, &m_weight, 8);
    return d;
  }
  void SetInterfaceIdx (uint32_t idx)
  {
    m_interfaceIdx = idx;
  }
  uint32_t GetInterfaceIdx () const
  {
    return m_interfaceIdx;
  }
  void SetState (uint16_t state)
  {
    m_state = state;
  }
  uint16_t GetState () const
  {
    return m_state;
  }
  void SetIEPair(struct IEPair s)
  {
    s.ingressAddr.Serialize(m_ingressAddr);
    s.egressAddr.Serialize(m_egressAddr);
  }
  struct IEPair GetIEPair() const
  {
    struct IEPair s;
    Ipv4Address ip;
    s.ingressAddr = ip.Deserialize(m_ingressAddr);
    s.egressAddr = ip.Deserialize(m_egressAddr);
    return s;
  }

  void SetPathLoss (double loss)
  {
    memcpy(&m_pathLoss, &loss,8);
  }
  double GetPathLoss () const
  {
    double d;
    memcpy(&d, &m_pathLoss, 8);
    return d;
  }

private:
  /*uint16_t m_packetLength;
  uint16_t m_packetSequenceNumber;*/
  uint64_t m_path_utilization;
  uint64_t m_positive_feedback;
  uint64_t m_negative_feedback;
  uint64_t m_weight;
  uint32_t m_interfaceIdx;
  uint16_t m_state; // 1 for a request 0 for feedback
  uint8_t m_ingressAddr[4];
  uint8_t m_egressAddr[4];
  uint64_t m_pathLoss;
public:  
  static TypeId GetTypeId (void);
  virtual TypeId GetInstanceTypeId (void) const;
  virtual void Print (std::ostream &os) const;
  virtual uint32_t GetSerializedSize (void) const;
  
  //virtual void Serialize (Buffer::Iterator start) const;
  //virtual uint32_t Deserialize (Buffer::Iterator start);

  virtual void Serialize (Buffer::Iterator start) const;
  virtual uint32_t Deserialize (Buffer::Iterator start);
};

class TexcpTag : public Tag 
{
public:
  TexcpTag ();
  virtual ~TexcpTag ();
  void SetTexcpSt (uint16_t state)
  {
    m_texcpSt = state;
  }
  uint16_t GetTexcpSt () const
  {
    return m_texcpSt;
  }
  void SetInterfaceIdx (uint32_t idx)
  {
    m_interfaceIdx = idx;
  }
  uint32_t GetInterfaceIdx () const
  {
    return m_interfaceIdx;
  }
private:
 uint16_t m_texcpSt; // 1 for a request 0 for feedbacj
 uint32_t m_interfaceIdx;
public:  
  static TypeId GetTypeId (void);
  virtual TypeId GetInstanceTypeId (void) const;
  virtual void Print (std::ostream &os) const;
  virtual uint32_t GetSerializedSize (void) const;
  
  virtual void Serialize (TagBuffer start) const;
  virtual void Deserialize (TagBuffer start);

  //virtual void Serialize (Buffer::Iterator start) const;
  //virtual uint16_t Deserialize (Buffer::Iterator start);
};


}} // namespace texcp, ns3

#endif /* OLSR_HEADER_H */

